---
title: Algolia Search
description: Integrate Algolia Search with Fumadocs
---

<Callout title="Notice">
  If you're using Algolia's free tier, you have to [display their logo on your
  search dialog](https://algolia.com/policies/free-services-terms).
</Callout>

## Introduction

The Algolia Integration automatically configures Algolia Search for document search.

It creates a record for **each paragraph** in your document, it is also recommended by Algolia.

Each record contains searchable attributes:

| Attribute | Description           |
| --------- | --------------------- |
| `title`   | Page Title            |
| `section` | Heading ID (nullable) |
| `content` | Paragraph content     |

The `section` field only exists in paragraphs under a heading. Headings and
paragraphs are indexed as an individual record, grouped by their page ID.

Notice that it expects the `url` property of a page to be unique, you shouldn't have two pages with the same
url.

## Setup

Install dependencies:

```package-install
algoliasearch
```

### Sign up on Algolia

Sign up and obtain the app id and API keys for your search. Store these
credentials in environment variables.

### Sync Search Indexes

Pre-render a static route `/static.json` to export search indexes into production build:

```ts title="lib/export-search-indexes.ts"
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';

export async function exportSearchIndexes() {
  const results: DocumentRecord[] = [];

  for (const page of source.getPages()) {
    results.push({
      _id: page.url,
      structured: page.data.structuredData,
      url: page.url,
      title: page.data.title,
      description: page.data.description,
    });
  }

  return results;
}
```

<include>.static-route-example.mdx</include>

Make a script to sync search indexes:

```ts title="scripts/sync-content.ts" twoslash
import { algoliasearch } from 'algoliasearch';
import { sync, DocumentRecord } from 'fumadocs-core/search/algolia';
import * as fs from 'node:fs';

// the path of pre-rendered `static.json`, choose one according to your React framework
const filePath = {
  next: '.next/server/app/static.json.body',
  'tanstack-start': '.output/public/static.json',
  'react-router': 'build/client/static.json',
  waku: 'dist/public/static.json',
}['next'];

const content = fs.readFileSync(filePath);

const records = JSON.parse(content.toString()) as DocumentRecord[];

const client = algoliasearch('id', 'key');

// update the index settings and sync search indexes
void sync(client, {
  indexName: 'document',
  documents: records,
});
```

Now run the script after build:

```json title="package.json"
{
  "scripts": {
    "build": "... && bun ./scripts/sync-content.ts"
  }
}
```

### Workflow

You may manually upload search indexes with the script, or integrate it with your CI/CD pipeline.

### Search UI

You can consider different options for implementing the UI:

- Using [Fumadocs UI search dialog](/docs/ui/search/algolia).
- Build your own using the built-in search client hook:

  ```ts twoslash
  import { liteClient } from 'algoliasearch/lite';
  import { useDocsSearch } from 'fumadocs-core/search/client';

  const client = liteClient('id', 'key');

  const { search, setSearch, query } = useDocsSearch({
    type: 'algolia',
    indexName: 'document',
    client,
  });
  ```

- Use their official clients directly.

## Options

### Tag Filter

To configure tag filtering, add a `tag` value to indexes.

```ts title="lib/export-search-indexes.ts"
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';

export async function exportSearchIndexes() {
  const results: DocumentRecord[] = [];

  for (const page of source.getPages()) {
    results.push({
      _id: page.url,
      structured: page.data.structuredData,
      url: page.url,
      title: page.data.title,
      description: page.data.description,
      // [!code ++]
      tag: '<your value>',
    });
  }

  return results;
}
```

And update your search client:

- **Fumadocs UI**: Enable [Tag Filter](/docs/ui/search/algolia#tag-filter) on Search UI.
- **Search Client**: You can add the tag filter like:

  ```ts
  import { useDocsSearch } from 'fumadocs-core/search/client';

  const { search, setSearch, query } = useDocsSearch({
    tag: '<your tag value>',
    // ...
  });
  ```

The `tag` field is an attribute for faceting. You can also use the filter `tag:value` on Algolia search clients.
